<?php

#	Fastfoo - CMS developer under CakePHP / http://fast-foo.com
#	Copyright (C) 2010  Antonio Irlandés García

#	This program is free software: you can redistribute it and/or modify
#	it under the terms of the GNU General Public License as published by
#	the Free Software Foundation, either version 3 of the License, or
#	(at your option) any later version.

#	This program is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.

#	You should have received a copy of the GNU General Public License
#	along with this program.  If not, see <http://www.gnu.org/licenses/>.

class GroupsController extends AppController{
	
	/*****************
	** Variables Generales
	*****************/
	public $name = 'Groups';//nombre controlador
	public $uses = array('Group', 'Aco', 'Aro', 'Permission');//modelos empleados
	public $layout = 'admin';//disposición de diseño por defecto

	/*****************
	** Variables Administracion
	*****************/
	public $search_form = true;//mostramos el buscador si o no
	public $cmp_search = 'Group.name';//campo de la BD que emplearemos para la BD (filtrar en las busquedas)
	public $sub_menu = array("users" => "index", "groups" => "index");//Subsecciones en submenu
	public $action_menu = array("list_groups" => "index","add_group"=>"view");//Acciones del menu accion
	public $lnregpp = array(20,40,60,80,100);//Numero de registros mostrados por pagina

	/*****************
	** Respuestas de controlador a una accion
	*****************/
	public $result_action;//Resultado de la operaciones
	public $msg_result;//Mensaje de la operacion

	/*****************
	** Otras variables
	*****************/
	private $_groups_protected = array(array('id' => '1','name' => 'administrators'), array('id' => '4','name' => 'guests'));//grupos protegidos por el sistema, no pueden ser modificados


////////////////////////////////////////////////////////////////////////////
//////*ESTOS METODOS DEBEN ESTAR LIMITADOS A LOS ADMINISTRADORES*//////////
//////////////////////////////////////////////////////////////////////////


	/**
	 * Listado de grupos en el panel de administración
	 *
	 * @return void
	 */
	public function admin_index(){

 		$this->layout = 'admin';

		//numero de registros a mostrar
		if(isset($this->params['named']['nreg']) && in_array($this->params['named']['nreg'],$this->lnregpp)){
			$i_array = array_keys($this->lnregpp,$this->params['named']['nreg']);
			$nreg = $this->lnregpp[$i_array[0]];
		}else{
			$nreg = $this->lnregpp[0];
		}
		
		//palabra a buscar
		(isset($this->params['named']['search'])) ? $search = $this->params['named']['search'] : $search = null;
		//pagina
		(isset($this->params['named']['Group'])) ? $page = $this->params['named']['Group'] : $page = 1;

		//Parametros que paso al paginador
		$this->paginate = array('limit' => $nreg,
								'order' => null,
								'conditions' => $this->cmp_search." LIKE '%".$search."%'",
								'recursive' => 2);

		//obtengo todos los registros y setemos
		$this->set('registers', $this->paginate('Group'));
		
		//menu derecho
		$this->set('action_menu', $this->action_menu);

		//submenu
		$this->set('sub_menu', $this->sub_menu);

		//Mostramos el buscador
		$this->set('search_form', $this->search_form);	

		//palabra buscada
		$this->set('search', $search);

		//lista de valores para mostrar por pantalla
		$this->set('lnregpp', $this->lnregpp);

		//pagina donde me encuentro
		$this->set('Group', $page);

		//Valor elegido en la lista de valores
		$this->set('nreg', $nreg);

	}


	/**
	 * Muestra registro pertinente
	 *
	 * @param integer $id indica el identificador del registro a mostrar
	 * @return void
	 */
	public function admin_view($id = null){

 		$this->layout = 'admin';

		//Seteo las secciones del menu izquierdo
		$this->set('action_menu', $this->action_menu);

		//Seteo las secciones del submenu
		$this->set('sub_menu', $this->sub_menu);

		//Mostramos el buscador
		$this->set('search_form', $this->search_form);	

		//Datos del registro
		$this->Group->id = $id;
        $this->set('register', $this->Group->read());
	}


	/**
	 * Añade o actualiza los registros de la BD
	 *
	 * @return void
	 */
	public function admin_add(){

 		$this->autoRender = false;
		
		if(!empty($this->data) && $this->RequestHandler->isAjax()){

			//Created
			if(empty($this->data['Group']['id']))
				$this->data['Group']['created'] = date("Y-m-d H:i:s"); 

			//Modified
			if(!empty($this->data['Group']['id']))
				$this->data['Group']['modified'] = date("Y-m-d H:i:s"); 

		
			//Aseguro la entrada de datos con sanitize
			$this->data = Sanitize::clean($this->data,
										  array('odd_spaces' => true,
												'encode' => false,
												'dollar' => true,
												'carriage' => true,
												'unicode' => true,
												'escape' => false,
												'backslash' => true));
		
		
			//Validamos la entrada de datos
			if ($this->Group->create($this->data) && $this->Group->validates() && $this->_checkGroupsProtected(array("id" => $this->data['Group']['id']))){
				//Salvamos los datos en la BD
				if ($this->Group->save($this->data)){

					####INICIO LOG del sistema
					if(isset($this->data['Group']['id']) && !empty($this->data['Group']['id'])){
						$id_reg = $this->data['Group']['id'];
						$action_reg = "update_group";

					}else{
						$id_reg = $this->Group->lastReg();
						$action_reg = "add_group";
					}

					$data_log = array ( "title" => "'".$this->data['Group']['name']."' (".__($action_reg, true).")",
										"section" => $this->name,
										"url" => Router::url(array('admin' => true,'controller'=> strtolower($this->name), 'action'=>'view', $id_reg), true),
										"created" => date("Y-m-d H:i:s")
										);

					$this->Log->addRegister($data_log);
					####FIN LOG

					//Mensaje a lanzar
					$this->result_action = true;
					$this->msg_result = "data_saved_correctly";
			
				}else{
					$this->result_action = false;
					$this->msg_result = "error_saving";
				}

			}else{
				//Errores
				$this->result_action = false;
				if(empty($this->msg_result))
					$this->msg_result = array_shift($this->validateErrors($this->Group));
			}

		}else{
			$this->result_action = false;
			$this->msg_result = "form_must_fill";
		}			

		//Para cuando se redirija mediante javascript siga mostrando el mensaje
		$url_redirect = Router::url(array('admin' => true,'action'=>'index'), true)."#result_system";
		$this->Session->setFlash(__($this->msg_result, true), 'default');

		//Devuelvo datos del mensaje e identificador (array --> json)
		echo (json_encode(array("result_action" => $this->result_action,
								"msg_result" => __($this->msg_result, true),
								"url_redirect" => $url_redirect
								)
						)
			);
	}




	/**
	 * Elimina registros de la BD
	 *
	 * @return void
	 */
	public function admin_delete(){

		if(isset($this->params['form']['list_reg'])){

			if(count($this->params['form']['list_reg']) != 0){

				for($i = 0; $i < count($this->params['form']['list_reg']); $i++){

					if($this->params['form']['list_reg'][$i] != ""){

						//Comprobamos que el grupo se puede borrar
						if($this->_checkGroupsProtected(array("id" => $this->params['form']['list_reg'][$i]))){

							####INICIO LOG del sistema
							$this->Group->id = $this->params['form']['list_reg'][$i];
							$data_register = $this->Group->read();

							//datos que se almacenarán en el LOG del sistema y la actividad de session del usuario
							$data_log = array ( "title" => "'".$data_register['Group']['name']."' (".__('deleted', true).")",
												"section" => $this->name,
												"url" => null,
												"created" => date("Y-m-d H:i:s")
												);

							$this->Log->addRegister($data_log);

							####FIN LOG

							///borramos grupos
							$this->Group->delete($this->params['form']['list_reg'][$i]);

							//datos a devolver
							$this->msg_result = "del_registers_correctly";
						}

					}else{
						//datos a devolver
						$this->msg_result = "error_process_delete";
					}
				}

			}else{
				//datos a devolver
				$this->msg_result = "select_one_register";
			}
				
		}else{
			//datos a devolver
			$this->msg_result = "no_operations";
		}

		//Mensaje que devuelve
		$this->Session->setFlash(__($this->msg_result, true), 'default');
		//Redireccion 
		$this->redirect($this->referer()."#result_system");
	}	

	/**
	 * Muestra los permisos que el grupo tiene habilitados en la BD
	 * 
	 * @return void
	 */
	public function admin_permissions($id){

		if(empty($id)){
			$this->redirect($this->referer());
		}else{

			//Menu nuevo
			$this->action_menu['manager_permissions'] = "permissions";

			//Seteo las secciones del menu izquierdo
			$this->set('action_menu', $this->action_menu);

			//Seteo las secciones del submenu
			$this->set('sub_menu', $this->sub_menu);

			//Mostramos el buscador
			$this->set('search_form', $this->search_form);	

			//Datos del registro
			$this->Group->id = $id;
	        $this->set('register', $this->Group->read());

			//Padre del arbol general de permisos(controllers => id = 1)
			$this->Aco->id = '1';
	        $data_root = $this->Aco->read();
			$this->set('data_root',$data_root);

			//Todas las acciones posibles listadas
			$registers_permissions = $this->Aco->find('all', array('fields' => array('id','alias','parent_id'), 'conditions' => 'parent_id IS NOT NULL AND lft >= "'.$data_root['Aco']['lft'].'" AND rght <= "'.$data_root['Aco']['rght'].'"','order' => 'lft ASC', "recursive" => "-1"));
			$this->set('registers_permissions', $registers_permissions);

			//Los permisos o privilegios que posee dicho grupo (marcados)
			$active_permissions = $this->Permission->find('all', array('conditions' => 'aro_id= "'.$id.'"', "recursive" => "-1"));

			//Averiguo que checkbox deben ser marcados
			foreach($registers_permissions as $register_permission){

				foreach($active_permissions as $active_permission){

					if($register_permission['Aco']['parent_id'] == $active_permission['Permission']['aco_id'] || $register_permission['Aco']['id'] == $active_permission['Permission']['aco_id']){//Su padre o el mismos
						$active_permissions_view[$active_permission['Permission']['aco_id']]['id'] = $active_permission['Permission']['aco_id'];
						$active_permissions_view[$active_permission['Permission']['aco_id']]['_read'] = $active_permission['Permission']['_read'];//Solo lo hago con el _read
					}
				}
			}

			//Indica que checkbox deben estar marcados
			$this->set('active_permissions_view',  $active_permissions_view);

		}

	}	


	/**
	 * Cambia los permisos del usuario en la BD
	 * 
	 * @return void
	 */
	public function admin_changePermissions(){
		
 		$this->autoRender = false;
		
		if(!empty($this->params['form']) && !empty($this->data)){
			//Grupo al que afecta el cambio
			$group_id = $this->data['Group']['id'];
			unset($this->data['Group']);

			//Obtengo los valores del ARO del grupo
			$data_aro_group = $this->Aro->find('first', array('conditions' => 'foreign_key = "'.$group_id.'" AND model = "Group"', "recursive" => "-1"));

			//Los permisos o privilegios que posee dicho grupo
			$bd_active_permissions = $this->Permission->find('all', array('conditions' => 'aro_id= "'.$data_aro_group['Aro']['id'].'"', "recursive" => "-1"));
			//Los nuevos asignados por el usuario
			$user_active_permissions = $this->_prepare_permissions($this->params['form']);

			//Se actualizan o se borran permisos
			foreach($bd_active_permissions as $bd_permission){

				if(isset($user_active_permissions[$bd_permission['Permission']['aco_id']])){//Actualizamos

					//Preparamos los datos
					$this->data['Permission']['id'] = $bd_permission['Permission']['id'];
					$this->data['Permission']['aro_id'] = $bd_permission['Permission']['aro_id'];
					$this->data['Permission']['aco_id'] = $bd_permission['Permission']['aco_id'];
					//Solo compruebo el _read
					(isset($user_active_permissions[$bd_permission['Permission']['aco_id']]['_read'])) ? $this->data['Permission']['_read'] = 1 : $this->data['Permission']['_read'] = 0;
					(isset($user_active_permissions[$bd_permission['Permission']['aco_id']]['_create'])) ? $this->data['Permission']['_create'] = 1 : $this->data['Permission']['_create'] = 0;
					(isset($user_active_permissions[$bd_permission['Permission']['aco_id']]['_update'])) ? $this->data['Permission']['_update'] = 1 : $this->data['Permission']['_update'] = 0;
					(isset($user_active_permissions[$bd_permission['Permission']['aco_id']]['_delete'])) ? $this->data['Permission']['_delete'] = 1 : $this->data['Permission']['_delete'] = 0;

					//Salvamos
					$this->Permission->save($this->data);
					//Lo eliminamos del array nuevo, los que sobren, seran de nueva inserccion
					unset($user_active_permissions[$bd_permission['Permission']['aco_id']]);

				}else{//Eliminamos
					$this->Permission->delete($bd_permission['Permission']['id']);
				}
				
			}

			//Inserccion de nuevos permisos
			if(count($user_active_permissions) > 0){
				foreach ($user_active_permissions as $user_permission){

					//Preparamos los datos
					$this->data['Permission']['id'] = null;
					$this->data['Permission']['aro_id'] = $data_aro_group['Aro']['id'];
					$this->data['Permission']['aco_id'] = $user_permission['aco_id'];
					(isset($user_permission['_read'])) ? $this->data['Permission']['_read'] = 1 : $this->data['Permission']['_read'] = 0;
					(isset($user_permission['_create'])) ? $this->data['Permission']['_create'] = 1 : $this->data['Permission']['_create'] = 0;
					(isset($user_permission['_update'])) ? $this->data['Permission']['_update'] = 1 : $this->data['Permission']['_update'] = 0;
					(isset($user_permission['_delete'])) ? $this->data['Permission']['_delete'] = 1 : $this->data['Permission']['_delete'] = 0;
				
					//Salvamos
					$this->Permission->save($this->data);
				}
			}

			####INICIO LOG del sistema
			$this->Group->id = $group_id;
			$data_register = $this->Group->read();

			$data_log = array ( "title" => __('update_permissions_group', true)." '".$data_register['Group']['name']."'",
								"section" => $this->name,
								"url" => Router::url(array('admin' => true,'controller'=> strtolower($this->name), 'action'=>'permissions', $data_register['Group']['id']), true),
								"created" => date("Y-m-d H:i:s")
								);

			$this->Log->addRegister($data_log);
			####FIN LOG

			//Mensaje a lanzar
			$this->msg_result = "data_saved_correctly";

		}else{
			$this->msg_result = "form_must_fill";
		}			

		//Mensaje que devuelve
		$this->Session->setFlash(__($this->msg_result, true), 'default');
		//Redireccion 
		$this->redirect($this->referer());

	}	

	/**
	 * Prepara los permisos que llegan del formulario para poder ser tratados en la función admin_changePermissions
	 *
	 * @param array $new_permissions de los checkbox marcados en el formulario
	 * @return array
	 */
	private function _prepare_permissions($new_permissions){

		//Por cada elemento enviado del formulario
		foreach ($new_permissions as $key => $value){
		
			$parts_key = explode("_", $key);

			//Aseguro que la entrada sea la correcta de datos
			if($parts_key[0] == 'reg' && is_numeric($parts_key[1])){

				$new_permissions_corrected[$parts_key[1]]['aco_id'] = $parts_key[1];
				$new_permissions_corrected[$parts_key[1]]['_read'] = $value;
				$new_permissions_corrected[$parts_key[1]]['_create'] = $value;
				$new_permissions_corrected[$parts_key[1]]['_update'] = $value;
				$new_permissions_corrected[$parts_key[1]]['_delete'] = $value;

			}

		}
		return $new_permissions_corrected;
	}


	/**
	 * Función que impide que borremos o modifiquemos accidentalmente grupos protegidos
	 * si lo hacen desde la BD eso ya no podré impedirlo
	 *
	 * @param array options para identificar al grupo a borrar
	 * @return bool
	 */
	private function _checkGroupsProtected($options, $groups = null){

		if(!empty($groups) && is_array($groups))
			$this->_groups_protected = $groups; //<-- lista de grupos que no pueden ser borrados

		//Recorro cada uno de los usuarios del array
		foreach ($this->_groups_protected as $group){
			if($options['id'] == $group['id'] || $options['name'] == $group['name']){
				$this->result_action = false;
				$this->msg_result = 'groups_protected';
				die();
				return false;
			}
		}

		return true;
	}

}

?>
